#include "stdafx.h"
#include "GeosTranf.h"
#include "assert.h"
#include <geos/geom/PrecisionModel.h>
#include <geos/geom/GeometryFactory.h>
#include <geos/geom/Geometry.h>
#include <geos/geom/Point.h>
#include <geos/geom/LinearRing.h>
#include <geos/geom/LineString.h>
#include <geos/geom/Polygon.h>
#include <geos/geom/GeometryCollection.h>
#include <geos/geom/Coordinate.h>
#include <geos/geom/CoordinateSequence.h>
#include <geos/geom/CoordinateArraySequence.h>
#include <geos/geom/IntersectionMatrix.h>
#include <geos/io/WKBReader.h>
#include <geos/io/WKBWriter.h>
#include <geos/io/WKTWriter.h>
#include <geos/util/GeometricShapeFactory.h>
#include <geos/util/GEOSException.h>
#include <geos/util/IllegalArgumentException.h>
#include <geos/opLinemerge.h>
#include <geos/opPolygonize.h>	  
#include <vector>
#include <sstream>
#include <iomanip>
#include <cstdlib> // exit()/
#include "PointStru.h"
#ifndef M_PI
#define M_PI       3.14159265358979323846
#endif

// Set to 0 to skip section
#define GEOMETRIC_SHAPES 1
#define RELATIONAL_OPERATORS 1
#define COMBINATIONS 1
#define UNARY_OPERATIONS 1
#define LINEMERGE 1
#define POLYGONIZE 1


using namespace std;
using namespace geos;
using namespace geos::geom;
using namespace geos::operation::polygonize;
using namespace geos::operation::linemerge;	   


GeometryFactory *global_factory;
CGeosTranf::CGeosTranf()
{
	method=M_INTERSECTION;	
}

CGeosTranf::~CGeosTranf()
{

}
bool CGeosTranf::PolygonOperator(dmDPoint *&ptsA,int &numA,dmDPoint *&ptsB,int &numB,dmDPoint **&ptsC,int *&numC,int &Total)
{
	CoordinateSequence *cl = new CoordinateArraySequence();
	CoordinateSequence *c2 = new CoordinateArraySequence();
	CoordinateSequence *c3 = new CoordinateArraySequence(); 


	for (int i=0;i<numA;i++)
	{
		cl->add(Coordinate(ptsA[i].x, ptsA[i].y));
	}
	for (int i=0;i<numB;i++)
	{
		c2->add(Coordinate(ptsB[i].x, ptsB[i].y));
	}

	PrecisionModel *pm = new PrecisionModel(2.0, 0.001, 0.001);
	global_factory = new GeometryFactory(pm, -1);
	delete pm;

	LinearRing *lr1 = global_factory->createLinearRing(cl);
	LinearRing *lr2 = global_factory->createLinearRing(c2);
		

	geos::geom::Polygon *pg1;
	geos::geom::Polygon *pg2;
	pg1=global_factory->createPolygon(lr1,NULL);
	pg2=global_factory->createPolygon(lr2,NULL);
	if(pg1->disjoint(pg2))
	{
		delete cl;
		delete c2;
		delete c3;
		delete global_factory;
		global_factory=NULL;
	  return false;
	}

	const Geometry *lr3,*lr4;
	switch (method)
	{
	case M_INTERSECTION: 
		lr3 = pg1->intersection(pg2);
		break;
	case  M_UNION:
		lr3 = pg1->Union(pg2);
		break;
	case M_DIFFERENCE:
		lr3 = pg1->difference(pg2);
		break;
	case M_SYMDIFFERENCE:
		lr3 = pg1->symDifference(pg2);
		break;
	default:
		break;
	}  

	int nNumGeos=0; 
	nNumGeos = lr3->getNumGeometries();
	Total= nNumGeos;
	ptsC=new dmDPoint*[nNumGeos];
	numC=new int[nNumGeos];
	for(int index=0;index<nNumGeos;++index)
	{
		lr4=lr3->getGeometryN(index);
		c3=lr4->getCoordinates();
		int numb = lr4->getNumPoints();
		ptsC[index]=new dmDPoint[numb];
		for (int i=0;i<numb;i++)
		{
			ptsC[index][i].x=c3->getX(i);
			ptsC[index][i].y=c3->getY(i);
			ptsC[index][i].z=0;
		}
		numC[index]=numb; 
		
	}
	 

	delete cl;
	delete c2;
	delete c3;	
	delete global_factory;
	global_factory=NULL;
	return true; 
}  


